#pragma once

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <cstring>
#include "Comm.hpp"

#define PATH "."
#define FILENAME "fifo"




class FifoHandler
{
public:
    // 构造函数，初始化FifoHandler对象
    // 参数包括FIFO文件的路径、文件名以及是否作为服务器端
    FifoHandler(bool is_server = true, const std::string &path = PATH, const std::string &name = FILENAME)
        : _path(path), _name(name), _fd(-1), _is_server(is_server)
    {
        _fifoname = _path + "/" + _name;

        if (_is_server)
        {
            // 服务端：创建FIFO（若不存在）
            umask(0);
            if (mkfifo(_fifoname.c_str(), 0666) < 0 && errno != EEXIST)
            {
                ERR_EXIT("mkfio");
            }
            std::cout << "FIFO is ready (created or already exists)" << std::endl;
        }
        else
        {
            // 客户端：仅检查FIFO是否存在
            if (access(_fifoname.c_str(), F_OK) < 0)
            {
                ERR_EXIT("FIFO not found");
            }
            std::cout << "Client: FIFO exists, ready to use" << std::endl;
        }
    }

    // 打开FIFO用于读取（阻塞等待写端）
    void OpenForRead()
    {
        _fd = open(_fifoname.c_str(), O_RDONLY);
        if (_fd < 0)
        {
            ERR_EXIT("Failed to open FIFO for reading");      
        }
        std::cout << "FIFO opened for reading" << std::endl;
    }

    // 打开FIFO用于写入（阻塞等待读端）
    void OpenForWrite()
    {
        _fd = open(_fifoname.c_str(), O_WRONLY);
        if (_fd < 0)
        {
            ERR_EXIT("Failed to open FIFO for writing");
        }
        std::cout << "FIFO opened for writing" << std::endl;
    }

    // 单次读取：读取一条消息（需先调用OpenForRead）
    ssize_t Read(char *buffer, size_t max_len)
    {
        if (_fd < 0)
        {
            ERR_EXIT("FIFO not opened for reading");
            return -1;
        }

        // 读取数据（最多读取max_len-1字节，留一个位置给'\0'）
        ssize_t number = read(_fd, buffer, max_len - 1);
        if (number < 0)
        {
            ERR_EXIT("Failed to read from FIFO");
            return -1;
        }
        else if (number == 0) // 读端关闭，read返回0
        {
            std::cout << "Read end closed, exit" << std::endl;
            return 0;
        }

        buffer[number] = '\0';
        return number;
    }

    bool Wait(char *c, size_t max_len)
    {
        int number = read(_fd, c, 1);
        if (number > 0)
            return true;
        return false;
    }

    // 写入数据（需先调用OpenForWrite）
    bool Write(const std::string &msg)
    {
        if (_fd < 0)
        {
            ERR_EXIT("FIFO not opened for writing");
            return false;
        }
        ssize_t number = write(_fd, msg.c_str(), msg.size());
        if (number < 0)
        {
            ERR_EXIT("Failed to write to FIFO");
            return false;
        }
        return true;
    }

    void Wakeup(char *c)
    {
        int n = write(_fd, c, 1);
        printf("唤醒: %d\n", n);
    }

    // 关闭FIFO
    void Close()
    {
        if (_fd != -1)
        {
            close(_fd);
            _fd = -1;
            std::cout << (_is_server ? "Server" : "Client") << ": FIFO closed" << std::endl;
        }
    }

    // 析构函数，清理FifoHandler对象
    ~FifoHandler()
    {
        // 关闭FIFO
        Close();
        // 通munication结束后删除FIFO
        if (_is_server)
        {
            if (unlink(_fifoname.c_str()) == 0)
            {
                std::cout << "FIFO removed" << std::endl;
            }
            else
            {
                std::cerr << "Failed to remove FIFO: " << strerror(errno) << std::endl;
            }
        }
        // 客户端：不执行unlink
    }

private:
    std::string _path;     // FIFO路径
    std::string _name;     // FIFO文件名
    std::string _fifoname; // FIFO完整路径
    int _fd;               // 文件描述符
    bool _is_server;       // 角色标识：true为服务端，false为客户端
};
